package com.fenghuo.myviews;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Path;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller;

import com.fenghuo.map.R;
import com.fenghuo.model.MapPoint;
import com.fenghuo.utils.Utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author Administrator
 */

/**
 * @author Administrator
 */
public class MapView extends View implements View.OnTouchListener,
        OnGestureListener {

    private Bitmap mbmp = null;// 地图
    private Bitmap bmp_arrow_r = null;
    private Bitmap bmp_arrow_l = null;
    private Bitmap bmp_location = null;

    // 图片的宽高就是地图的宽高
    private int bmpwidth;// 实际宽度
    private int bmpheigth;
    private int dispwidth;// 当前显示的缩放图片的宽度
    private int dispheight;
    private int screenwidth;// 控件宽度
    private int screenheight;
    private int scaleCenterx, scaleCentery;//  图片的缩放中心
    private static final float pradius = 25;//  点的可点半径
    private int pradius_self = 8;//自身半径

    private int offsetX;// 偏移量
    private int offsetY;
    private int disRight = 0;//当前显示的图片的上下左右 边界坐标
    private int disLeft = 0;
    private int disUp = 0;
    private int disBottom = 0;

    private int locationx;    // 定位
    private int locationy;
    private int locationr;
    private boolean haveloc = false;

    private Scroller mscroller;// 滑动
    private GestureDetector mgestureDetector;// 手势

    private float mscale;// 当前图片的缩放倍率 1为没有缩放
    private float minscale;// x最小的缩放比
    private float maxscale;
    private float yscale;//开始加载时 y轴的缩放量

    private Matrix matrix;
    private List<MapPoint> list;//点
    private MapPoint pcurrent;//当前点击状态的点
    private RectF prectF;//点击点后的弹窗

    private Paint mpaintblue;//弹窗
    private Paint mpaintpoint;//黄点
    private Paint mpainttext;//文字
    private Paint mpaintlocationr;//画位置半径
    private Paint mpaintsearch;

    private OnLayoutListener layoutListener;
    private OnClickPointListener clickPointListener;

    private ExecutorService service = null;

    public MapView(Context context) {
        super(context);
        init(context);
    }

    public MapView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        setClickable(true);
        setLongClickable(true);
        setOnTouchListener(this);

        bmp_arrow_r = BitmapFactory.decodeResource(getResources(), R.drawable.pop_place_arrow_r);
        bmp_arrow_l = rotateBitmap(bmp_arrow_r, 180);
        bmp_location = BitmapFactory.decodeResource(getResources(), R.drawable.img_location);
        mgestureDetector = new GestureDetector(context, this);
        mscroller = new Scroller(context, new DecelerateInterpolator());
        list = new ArrayList<MapPoint>();

        matrix = new Matrix();
        mpaintblue = new Paint();
        mpaintblue.setColor(Color.parseColor("#61C1BD"));
//		mpaintblue.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.DARKEN));

        mpaintpoint = new Paint();//#F69B16 橘黄  #06608E 蓝绿
        mpaintpoint.setColor(Color.parseColor("#F69B16"));

        mpaintlocationr = new Paint();
        mpaintlocationr.setColor(Color.parseColor("#61c1ee"));
        mpaintlocationr.setAlpha(180);
        mpaintlocationr.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.DARKEN));

        mpainttext = new Paint();
        mpainttext.setColor(Color.WHITE);
        mpainttext.setTextSize(Utils.getpx(getContext(), 18));

        service = Executors.newSingleThreadExecutor();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right,
                            int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (changed && right > 0 && layoutListener != null) {
            layoutListener.onlayout(right, bottom);
            layoutListener = null;
        }
    }

    public void computeScroll() {
        if (mscroller.computeScrollOffset()) {
            scrollTo(mscroller.getCurrX(), mscroller.getCurrY());
            postInvalidate();
        } else {
//			checkposition();  [没有回弹  根本滑不出范围]
        }
    }

    ;

    //大学软件学院:(278,150)
    //大学软件学院宿舍5号楼:(98,662);

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.drawBitmap(mbmp, matrix, mpaintpoint);

        //画地点
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                MapPoint point = list.get(i);
                canvas.drawCircle(getimgx(point.getX()), getimgy(point.getY()), 8 * mscale, mpaintpoint);
                //canvas.drawCircle(getimgx(point.getX()), getimgy(point.getY()), pradius*mscale, mpaint);
            }
        }

        //我的位置
        if (haveloc) {
            int locx = getimgx(locationx);
            int locy = getimgy(locationy);
            canvas.drawCircle(locx, locy, locationr * mscale, mpaintlocationr);
            canvas.drawBitmap(bmp_location, locx - bmp_location.getWidth() / 2, locy - bmp_location.getHeight(), null);
        }

        //弹窗  （居然这么多）
        if (pcurrent != null) {
            //计算文字长度
            int x = getimgx(pcurrent.getX());//图片上的点
            int y = getimgy(pcurrent.getY());
            //[上下左右 边界]
            float onew = mpainttext.measureText("上下左右边界") / 6;
            int lenth = (int) mpainttext.measureText(pcurrent.getName());
            int width = lenth + (int) onew * 3;
            FontMetrics fm = mpainttext.getFontMetrics();
            int height = (int) (Math.ceil(fm.descent - fm.ascent));  //得到文字 高度

            float left = x - width / 4;
            float top = y - height * 2.5f;
            float right = x + width * 3 / 4;
            float bottom = y - height;

            if (x > disRight - 180 * mscale) {
                //在右边缘
                left = x - width * 4 / 5;
                right = x + width * 1 / 5;
                prectF = new RectF(left, top, right, bottom);
                canvas.drawRoundRect(prectF, 6, 6, mpaintblue);//画矩形
                canvas.drawBitmap(bmp_arrow_l, left + 0.5f, top - 4, null);//画箭头
                canvas.drawText(pcurrent.getName(), left + 1.5f * onew, top + height, mpainttext);
            } else {
                prectF = new RectF(left, top, right, bottom);
                canvas.drawRoundRect(prectF, 6, 6, mpaintblue);//画矩形
                canvas.drawBitmap(bmp_arrow_r, left + onew + lenth + onew / 2, top, null);//画箭头
                canvas.drawText(pcurrent.getName(), left + onew, top + height, mpainttext);
            }
            Path path = new Path();
            path.moveTo(x, y);
            path.lineTo(x - Utils.getpx(getContext(), 5), y - height);
            path.lineTo(x + Utils.getpx(getContext(), 5), y - height);
            path.close();
            canvas.drawPath(path, mpaintblue);//画三角

        }
    }

    // ----------------触屏-------------------//


    private float distance;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN
                && event.getEdgeFlags() != 0) {
            return false;
        }
        mgestureDetector.onTouchEvent(event);// 负责处理 点击、拖动、滑动

        switch (event.getAction()) { // 负责处理 缩放
            case MotionEvent.ACTION_DOWN:// 在第一个点被按下时触发
                break;
            case MotionEvent.ACTION_POINTER_DOWN:// 当屏幕上已经有一个点被按住，此时再按下其他点时触发。
                int dx0 = (int) event.getX(0);// 相对屏幕的坐标
                int dy0 = (int) event.getY(0);
                int dx1 = (int) event.getX(1);
                int dy1 = (int) event.getY(1);
                distance = (float) Math.sqrt((dx1 - dx0) * (dx1 - dx0) + (dy1 - dy0) * (dy1 - dy0));// 第二个手指按下时 两个手指的距离
                break;
            case MotionEvent.ACTION_MOVE:
                if (event.getPointerCount() > 1) {
                    int dx3 = (int) event.getX(0);
                    int dy3 = (int) event.getY(0);
                    int dx4 = (int) event.getX(1);
                    int dy4 = (int) event.getY(1);
                    float newdistance = (float) Math.sqrt((dx4 - dx3) * (dx4 - dx3) + (dy4 - dy3) * (dy4 - dy3));// 滑动后的新距离
                    float d = newdistance - distance;

                    if (Math.abs(d) > 1) {
                        matrix.reset();
                        if (d > 0) {// 放大
                            if (mscale < maxscale) {
                                mscale = mscale + 0.05f;
                                dispheight = (int) (bmpheigth * mscale);
                                dispwidth = (int) (bmpwidth * mscale);
                            }
                        } else {// 缩小
                            if (mscale > minscale) {
                                mscale = mscale - 0.05f;
                                dispheight = (int) (bmpheigth * mscale);
                                dispwidth = (int) (bmpwidth * mscale);
                            }
                        }
                        disLeft = scaleCenterx - dispwidth / 2;
                        disRight = scaleCenterx + dispwidth / 2;
                        disBottom = scaleCentery + dispheight / 2;
                        disUp = scaleCentery - dispheight / 2;
                        matrix.setScale(mscale, mscale, scaleCenterx, scaleCentery);
                        distance = newdistance;
                        invalidate();
                    }
                }
                break;

            case MotionEvent.ACTION_POINTER_UP:// 当屏幕上有多个点被按住，松开其中一个点时触发（即非最后一个点被放开时）
                break;
            case MotionEvent.ACTION_UP:
                checkposition();                    //有回弹 可以滑出范围 但是会弹回来
                break;
            default:
                break;
        }
        return false;
    }

    // ----------------手势-------------------//

    @Override
    public boolean onDown(MotionEvent e) {
//		 System.out.println("========onDown==========="+e.getPointerCount());

        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {
        // System.out.println("========onShowPress===========");
    }

    int count = 0;

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
//		 System.out.println("========onSingleTapUp==========="+e.toString()+e.getPointerCount());
        if (this.clickPointListener != null) {
            if (pcurrent != null && checkpcurrent(e)) {//检查是否点击 弹窗
                clickPointListener.oncklick(list.indexOf(pcurrent));
                return true;
            } else {
                pcurrent = null;
                invalidate();
                checkPoint((int) e.getX(), (int) e.getY());
            }
        }
        count++;
        if (count == 2) {
//			System.out.println(mscale+"count=============="+maxscale);
            myTask task = new myTask();
            if (android.os.Build.VERSION.SDK_INT >= 11) {
                task.executeOnExecutor(service);
            } else {
                task.execute();
            }
            return true;
        }
        new Timer().schedule(new TimerTask() {

            @Override
            public void run() {
                count = 0;
            }
        }, 500);
        return false;
    }


    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
                            float distanceY) {
        scrollBy((int) distanceX, (int) distanceY);
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                           float velocityY) {
//		mscroller.fling(getScrollX(), getScrollY(), -(int) velocityX / 2,-(int) velocityY / 2, 0, dispwidth, 0,dispheight);
//		invalidate();
        return false;
    }


    /**
     * 缩放动画
     *
     * @author Administrator
     */
    class myTask extends AsyncTask<Void, Void, Void> {

        float zl = 0.0f;
        boolean b = true;

        @Override
        protected void onPreExecute() {
            zl = 0;
            b = true;
            super.onPreExecute();
        }


        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
            invalidate();
        }


        @Override
        protected Void doInBackground(Void... params) {
            while (b) {
                if (mscale < maxscale) {
                    if (zl < 0.5) {
                        mscale += 0.05f;
                        zl += 0.05f;
                        matrix.reset();
                        disLeft = scaleCenterx - dispwidth / 2;
                        disRight = scaleCenterx + dispwidth / 2;
                        disBottom = scaleCentery + dispheight / 2;
                        disUp = scaleCentery - dispheight / 2;
                        dispwidth = (int) (bmpwidth * mscale);
                        dispheight = (int) (bmpheigth * mscale);
                        matrix.postScale(mscale, mscale, scaleCenterx, scaleCentery);
                        publishProgress();
                        try {
                            Thread.sleep(25);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        b = false;
                    }
                } else {
                    b = false;
                }
            }
            return null;
        }
    }

    /**
     * 根据真实坐标x 计算应该在当前缩放下的坐标x
     *
     * @param x
     * @return
     */
    private int getimgx(int x) {
        int cx = this.scaleCenterx;
        float scale = this.mscale;
        return (int) (cx - dispwidth / 2 + x * scale);
    }

    /**
     * 根据真实坐标y 计算应该在当前缩放下的坐标y
     *
     * @param y
     * @return
     */
    private int getimgy(int y) {
        int cy = this.scaleCentery;
        float scale = this.mscale;
        return (int) (cy - dispheight / 2 + (y * yscale) * scale);
    }

    /**
     * 得到真实坐标
     *
     * @param downx_
     * @param downy_
     * @return
     */
    private int getrealx(int screenx) {
        return screenx + getScrollX();
    }

    private int getrealy(int screeny) {
        return screeny + getScrollY();
    }

    /**
     * 点击
     *
     * @param downx
     * @param downy
     * @return
     */
    private int checkPoint(int downx, int downy) {

        int realx = getrealx(downx);// 按下的坐标
        int realy = getrealy(downy);
        for (int i = 0; i < list.size(); i++) {
            MapPoint p = list.get(i);
            int px = getimgx(p.getX());// 图片的坐标
            int py = getimgy(p.getY());
            if ((px - realx) * (px - realx) + (py - realy) * (py - realy) < pradius * pradius * mscale * mscale) {
                pcurrent = p;
                invalidate();
                return i;
            }
        }

        return -1;
    }

    private boolean checkpcurrent(MotionEvent e) {
        int x = getrealx((int) e.getX());
        int y = getrealy((int) e.getY());
        int left = (int) prectF.left;
        int top = (int) prectF.top;
        int right = (int) prectF.right;
        int bottom = (int) prectF.bottom;
        if (x < left) {
            return false;
        } else if (x > right) {
            return false;
        } else if (y < top) {
            return false;
        } else if (y > bottom) {
            return false;
        }
        return true;
    }

    private void checkposition() {
        int leftmar = checkLeft();
        int topmar = checkUp();
        int rightmar = checkRight();
        int bottommar = checkBottom();
        int scrollx = 0;
        int scrolly = 0;
        scrollx = leftmar + rightmar;
        scrolly = topmar + bottommar;
        scrollBy(scrollx, scrolly);
    }

    private int checkLeft() {
        int d = disLeft - getScrollX();
        if (d > 0)
            return d;
        else
            return 0;
    }

    private int checkUp() {
        int d = disUp - getScrollY();
        if (d > 0)
            return d;
        return 0;
    }

    private int checkRight() {
        int d = disRight - (getScrollX() + screenwidth);
        if (d < 0)
            return d;
        return 0;
    }

    private int checkBottom() {
        int d = disBottom - (getScrollY() + screenheight);
        if (d < 0)
            return d;
        return 0;
    }

    // ----------------方法-------------------//

    /**
     * 更新我的位置
     *
     * @param x
     * @param y
     * @param have
     * @param radius
     */
    public void updatelocation(int x, int y, boolean have, int radius) {
        this.haveloc = have;
        this.locationx = x;
        this.locationy = y;
        this.locationr = radius;
        invalidate();
    }

    public void setBmp(Bitmap bitmap, int height, int width) {
        System.out.println(bitmap.getHeight() + "=======缩放前=====" + bitmap.getWidth());
        // 生成适屏的bitmap
        float sp = width * 1.0f / height;//屏幕的宽高比
        yscale = bitmap.getWidth() / (sp * bitmap.getHeight());
        Matrix m = new Matrix();
        m.reset();
        m.postScale(1, yscale, 0, 0);
        this.mbmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, false);
//		bitmap.recycle();
        bitmap = null;
        // 图片宽高
        this.bmpheigth = mbmp.getHeight();
        this.bmpwidth = mbmp.getWidth();
        System.out.println(bmpheigth + "缩放后" + bmpwidth);
        // 控件宽高
        this.screenheight = height;
        this.screenwidth = width;
        // 初始化Matrix
        this.mscale = screenwidth / (float) bmpwidth;
        this.minscale = mscale;
        System.out.println("=======mscale==============" + mscale);
        this.maxscale = mscale * 2;
        this.scaleCenterx = (int) (bmpwidth * 0.5f);
        this.scaleCentery = (int) (bmpheigth * 0.5f);
        this.matrix.setScale(mscale, mscale, scaleCenterx, scaleCentery); //初始缩放中心
        this.offsetX = (int) (scaleCenterx - width / 2);
        this.offsetY = (int) (scaleCentery - height / 2);
        scrollTo(offsetX, offsetY); // 现 120,154(图片大小、屏幕大小 影响)
        // 初始化 显示的图片的宽度
        this.dispheight = screenheight;
        this.dispwidth = screenwidth;
        this.disLeft = scaleCenterx - dispwidth / 2;
        this.disRight = scaleCenterx + dispwidth / 2;
        this.disBottom = scaleCentery + dispheight / 2;
        this.disUp = scaleCentery - dispheight / 2;
        invalidate();
    }

    public void setData(List<MapPoint> data) {
        this.list = data;
        invalidate();
    }

    /**
     * 重置地图
     */
    public void resetmap() {
        mscale = minscale;
        this.matrix.setScale(mscale, mscale, scaleCenterx, scaleCentery); //初始缩放中心
        this.offsetX = (int) (scaleCenterx * 0.5f * mscale);
        this.offsetY = (int) (scaleCentery * 0.5f * mscale);
        scrollTo(offsetX, offsetY); // 现 120,154(图片大小、屏幕大小 影响)
        this.dispheight = (int) (bmpheigth * mscale);
        this.dispwidth = (int) (bmpwidth * mscale);
        this.disLeft = scaleCenterx - dispwidth / 2;
        this.disRight = scaleCenterx + dispwidth / 2;
        this.disBottom = scaleCentery + dispheight / 2;
        this.disUp = scaleCentery - dispheight / 2;
    }

    //开始检索
    public void search(List<MapPoint> data) {
        this.list = null;
        this.list = data;
        pradius_self = 15;
        mpaintpoint.setColor(Color.parseColor("#06608E"));
        resetmap();
        invalidate();
    }

    //退出检索
    public void quitsearch(List<MapPoint> data) {
        this.list = null;
        this.list = data;
        pradius_self = 8;
        mpaintpoint.setColor(Color.parseColor("#F69B16"));
        invalidate();
    }

    public static Bitmap rotateBitmap(Bitmap bm, int rotate) {
        Bitmap BitmapOrg = bm;
        int width = BitmapOrg.getWidth();
        int height = BitmapOrg.getHeight();
        Matrix matrix = new Matrix();
        matrix.setRotate(rotate);
        return Bitmap.createBitmap(BitmapOrg, 0, 0, width, height, matrix, true);
    }

    /**
     * 只发生一次
     *
     * @param listener
     */
    public void setOnLayoutListener(OnLayoutListener listener) {
        this.layoutListener = listener;
    }

    /**
     * 设置点击监听 点击圆点弹出弹窗  点击弹窗才会发生 ClickPoint.click
     *
     * @param listener
     */
    public void setOnClickPointListener(OnClickPointListener listener) {
        this.clickPointListener = listener;
    }

    public interface OnClickPointListener {
        void oncklick(int id);
    }

    public interface OnLayoutListener {
        void onlayout(int width, int height);
    }
}
